import {
  type AnnotationReply,
  type Conversation,
  type MessageEnd,
  type MessageReplace,
  type NodeFinishedResponse,
  type NodeStartedResponse,
  type RecordItem,
  type SendMessageRequest,
  type ThoughtItem,
  type VisionFile,
  type WorkflowFinishedResponse,
  type WorkflowStartedResponse,
} from '@/types'
import request from '@/utils/request'
import type { AppInfoResponse, AppParametersResponse, CustomResponse } from 'axios'
import { useToast } from 'vue-toastification'

export type IOnDataMoreInfo = {
  conversationId?: string
  taskId?: string
  messageId: string
  errorMessage?: string
  errorCode?: string
}

export type IOnData = (message: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => void
export type IOnCompleted = (hasError?: boolean) => void
export type IOnThought = (though: ThoughtItem) => void
export type IOnFile = (file: VisionFile) => void
export type IOnMessageEnd = (messageEnd: MessageEnd) => void
export type IOnMessageReplace = (messageReplace: MessageReplace) => void
export type IOnAnnotationReply = (messageReplace: AnnotationReply) => void
export type IOnError = (msg: string, code?: string) => void
export type IOnWorkflowStarted = (workflowStarted: WorkflowStartedResponse) => void
export type IOnWorkflowFinished = (workflowFinished: WorkflowFinishedResponse) => void
export type IOnNodeStarted = (nodeStarted: NodeStartedResponse) => void
export type IOnNodeFinished = (nodeFinished: NodeFinishedResponse) => void

const toast = useToast()

const unicodeToChar = (text: string) => {
  return text.replace(/\\u[0-9a-f]{4}/g, (_match, p1) => {
    return String.fromCharCode(parseInt(p1, 16))
  })
}

// 发送消息
export const sendMessage = (data: SendMessageRequest) => {
  const headers: HeadersInit = {
    'Content-Type': 'application/json;charset=utf-8',
  }
  const isNative = import.meta.env.VITE_API_NATIVE === 'true'
  // 在请求发送之前做一些处理
  if (isNative) {
    headers['Authorization'] = 'Bearer ' + import.meta.env.VITE_API_KEY
  } else {
    // TODO 设置Token
    // config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
  }

  return fetch(`${import.meta.env.VITE_BASE_API}/chat-messages`, {
    method: 'POST',
    headers,
    body: JSON.stringify(data),
  })
}

// 处理流式响应
export const handleStream = async (
  response: Response,
  onData: IOnData,
  onCompleted?: IOnCompleted,
  onThought?: IOnThought,
  onMessageEnd?: IOnMessageEnd,
  onMessageReplace?: IOnMessageReplace,
  onFile?: IOnFile,
  onWorkflowStarted?: IOnWorkflowStarted,
  onWorkflowFinished?: IOnWorkflowFinished,
  onNodeStarted?: IOnNodeStarted,
  onNodeFinished?: IOnNodeFinished,
  onError?: IOnError,
) => {
  if (!/^(2|3)\d{2}$/.test(String(response.status))) {
    new Promise(() => {
      response.json().then((data) => {
        toast.error(data.message || 'Server Error')
      })
    })
    onError?.('Server Error')
    onCompleted?.(true)
    return
  }
  if (!response.ok) throw new Error('Network response was not ok')
  const reader = response.body?.getReader()
  const decoder = new TextDecoder('utf-8')
  let buffer = ''
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let bufferObj: Record<string, any>
  let isFirstMessage = true
  const read = () => {
    let hasError = false
    reader?.read().then((result) => {
      if (result.done) {
        onCompleted?.()
        return
      }
      buffer += decoder.decode(result.value, { stream: true })
      const lines = buffer.split('\n')
      try {
        for (const message of lines) {
          if (message.startsWith('data:')) {
            try {
              bufferObj = JSON.parse(message.slice(6))
            } catch {
              onData('', isFirstMessage, {
                conversationId: bufferObj?.conversation_id,
                messageId: bufferObj?.message_id,
              })
              continue
            }
            if (bufferObj.status === 400 || bufferObj.event === 'error' || !bufferObj.event) {
              onError?.(bufferObj.message)
              hasError = true
              onCompleted?.(true)
              return
            }
            if (bufferObj.event === 'message' || bufferObj.event === 'agent_message') {
              // can not use format here. Because message is splited.
              onData(unicodeToChar(bufferObj.answer), isFirstMessage, {
                conversationId: bufferObj.conversation_id,
                taskId: bufferObj.task_id,
                messageId: bufferObj.id,
              })
              isFirstMessage = false
            } else if (bufferObj.event === 'agent_thought') {
              onThought?.(bufferObj as ThoughtItem)
            } else if (bufferObj.event === 'message_file') {
              onFile?.(bufferObj as VisionFile)
            } else if (bufferObj.event === 'message_end') {
              onMessageEnd?.(bufferObj as MessageEnd)
            } else if (bufferObj.event === 'message_replace') {
              onMessageReplace?.(bufferObj as MessageReplace)
            } else if (bufferObj.event === 'workflow_started') {
              onWorkflowStarted?.(bufferObj as WorkflowStartedResponse)
            } else if (bufferObj.event === 'workflow_finished') {
              onWorkflowFinished?.(bufferObj as WorkflowFinishedResponse)
            } else if (bufferObj.event === 'node_started') {
              onNodeStarted?.(bufferObj as NodeStartedResponse)
            } else if (bufferObj.event === 'node_finished') {
              onNodeFinished?.(bufferObj as NodeFinishedResponse)
            }
          }
        }
        buffer = lines[lines.length - 1]
      } catch (error) {
        onData('', false, {
          conversationId: undefined,
          messageId: '',
          errorMessage: `${error}`,
        })
        hasError = true
        onCompleted?.(true)
        return
      }
      if (!hasError) read()
    })
  }
  read()
}

// 获取会话列表
export const getConversationList = (
  params?: { pinned?: boolean; user?: string; limit?: number; last_id: string } | undefined,
) => {
  return request.get('/conversations', { params }) as Promise<CustomResponse<Conversation[]>>
}

// 获取会话历史消息
export const getConversationById = (params: {
  conversation_id: string
  user: string
  limit?: number
  first_id?: string
}) => {
  return request.get('/messages', { params }) as Promise<CustomResponse<RecordItem[]>>
}

// 删除会话
export const deleteConversation = (id: string, user: string) => {
  return request.delete(`/conversations/${id}`, { data: { user } })
}

// 重命名会话
export const renameConversation = (id: string, name: string, user: string) => {
  return request.post(`/conversations/${id}/name`, { name, user })
}

// 获取应用基本信息
export const getAppInfo = () => {
  return request.get('/info') as Promise<AppInfoResponse>
}

// 获取应用参数
export const getAppParameters = () => {
  return request.get('/parameters') as Promise<AppParametersResponse>
}

// 获取应用meta信息
export const getAppMeta = () => {
  return request.get('/meta')
}
